opengl高级光照

您所在的位置:网站首页 2d贴图 阴影渲染 opengl高级光照

opengl高级光照

2024-01-12 22:08| 来源: 网络整理| 查看: 265

第一步我们需要生成一张深度贴图(Depth Map)。深度贴图是从光的透视图里渲染的深度纹理,用它计算阴影。因为我们需要将场景的渲染结果储存到一个纹理中,我们将再次需要帧缓冲。

// configure depth map FBO // ----------------------- const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; //为渲染的深度贴图创建一个帧缓冲对象 unsigned int depthMapFBO; glGenFramebuffers(1, &depthMapFBO); //创建一个2D纹理,提供给帧缓冲的深度缓冲使用 //把纹理格式指定为GL_DEPTH_COMPONENT。我们还要把纹理的高宽设置为1024:这是深度贴图的分辨率。 unsigned int depthMap; glGenTextures(1, &depthMap); glBindTexture(GL_TEXTURE_2D, depthMap); //NULL表示纹理内容暂时为空,是需要在帧缓冲中被写入的 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 把生成的深度纹理作为帧缓冲的深度缓冲: glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); //指明不需要color buffer glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); // shader configuration // -------------------- debugDepthQuad.useShader(); debugDepthQuad.setInt("depthMap", 0);//在shader中的名字设为0 // lighting info // ------------- glm::vec3 lightPos(-2.0f, 4.0f, -1.0f);

while循环中:合理配置将深度值渲染到纹理的帧缓冲后,我们就可以开始第一步了 光的空间变换:因为我们使用的是一个所有光线都平行的定向光。出于这个原因,我们将为光源使用正交投影矩阵(其它的就要变成齐次的,要回归线性),透视图将没有任何变形。为了创建一个视图矩阵来变换每个物体,把它们变换到从光源视角可见的空间中,我们将使用glm::lookAt函数;这次从光源的位置看向场景中央。二者相结合为我们提供了一个光空间的变换矩阵 注意:1.渲染的时候结束绑定纹理操作。2.文档代码和实际代码是不同的

// -------------------------------------------------------------- //注意这里使用了将视角路线作为光的路线 glm::mat4 lightProjection, lightView; glm::mat4 lightSpaceMatrix; float near_plane = 1.0f, far_plane = 7.5f; lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); lightSpaceMatrix = lightProjection * lightView; simpleDepthShader.useShader(); simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix); //真正的渲染步骤 // 1. 首选渲染深度贴图 (from light's perspective) glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);//激活绑定纹理 glClear(GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, woodTexture); renderScene(simpleDepthShader); glBindFramebuffer(GL_FRAMEBUFFER, 0);//结束绑定 // 重置glViewport glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // render Depth map to quad for visual debugging(渲染平面) // --------------------------------------------- debugDepthQuad.useShader(); debugDepthQuad.setFloat("near_plane", near_plane); debugDepthQuad.setFloat("far_plane", far_plane); glActiveTexture(GL_TEXTURE0);//这里的0对应的是上面传入shader中纹理单元的depthMap值 glBindTexture(GL_TEXTURE_2D, depthMap); renderQuad();

这里一定要记得调用glViewport。因为阴影贴图经常和我们原来渲染的场景(通常是窗口分辨率)有着不同的分辨率,我们需要改变视口(viewport)的参数以适应阴影贴图的尺寸。如果我们忘了更新视口参数,最后的深度贴图要么太小要么就不完整。

渲染至深度贴图 顶点着色器

#version 330 core layout (location = 0) in vec3 position; uniform mat4 lightSpaceMatrix; uniform mat4 model; void main() { gl_Position = lightSpaceMatrix * model * vec4(position, 1.0f); }

片段着色器:受否由gl_FragDepth 都会出发

#version 330 core void main() { // gl_FragDepth = gl_FragCoord.z; }

结果 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3